package com.bc.db;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public abstract class GenericDao<T> extends BaseDao {

	private static final String[] COUNT_COLUMN = { "COUNT(1)" };

	public GenericDao(Context context) {
		super(context);
	}

	/** 将一个实体保存到数据库中 */
	public void addItem(T entity) {
		DBHelper dbHelper =DBHelper.getInstance();
		SQLiteDatabase db = null;
		try {
			db = dbHelper.getWritableDatabase();
			ContentValues values = new ContentValues();
			setItem(values, entity);
			db.insert(getTable(), null, values);
		} finally {
			close(null, db);
		}
	}

	/**
	 * 将列表中的实体保存到数据库中
	 * 
	 * @param list
	 */
	public void addItems(List<T> list) {
		if (list == null)
			return;
		DBHelper dbHelper = DBHelper.getInstance();
		SQLiteDatabase db = null;
		try {
			db = dbHelper.getWritableDatabase();
			db.beginTransaction();
			for (T entity : list) {
				ContentValues values = new ContentValues();
				setItem(values, entity);
				db.insert(getTable(), null, values);				
			}
			db.setTransactionSuccessful();
		} finally {
			db.endTransaction();
			close(null, db);
		}
	}

	/** 提供给子类的一个便捷方法，用于更新一个实体 */
	public void updateItem(T entity, String whereClause, String[] whereArgs) {
		DBHelper dbHelper = DBHelper.getInstance();;
		SQLiteDatabase db = null;
		try {
			db = dbHelper.getWritableDatabase();
			ContentValues values = new ContentValues();
			setItem(values, entity);
			db.update(getTable(), values, whereClause, whereArgs);
		} finally {
			close(null, db);
		}
	}

	/**
	 * 查询表中的所有数据
	 * 
	 * @return
	 */
	public ArrayList<T> queryItems() {
		return queryItems(null, null);
	}

	/**
	 * 提供给子类的一个便捷方法
	 * 
	 * @param selection
	 *            查询条件，比如id=? and name=?
	 * @param selectionArgs
	 *            对查询条件赋值，一个问号对应一个值
	 * @return
	 */
	public ArrayList<T> queryItems(String selection, String[] selectionArgs) {
		DBHelper dbHelper = DBHelper.getInstance();;
		ArrayList<T> list = new ArrayList<T>();

		SQLiteDatabase db = null;
		Cursor cursor = null;
		try {
			db = dbHelper.getReadableDatabase();
			cursor = db.query(getTable(), getColumns(), selection, selectionArgs, null, null, getOrderBy());
			while (cursor.moveToNext()) {
				T c = getItem(cursor);
				list.add(c);
			}

		} finally {
			close(cursor, db);
		}
		return list;
	}

	/**
	 * 查询指定的实体
	 * 
	 * @param itemID
	 *            该实体的id
	 * @return
	 */
	public T queryItem(String itemID) {
		DBHelper dbHelper = DBHelper.getInstance();;
		T entity = null;

		SQLiteDatabase db = null;
		Cursor cursor = null;
		try {
			db = dbHelper.getReadableDatabase();
			cursor = db.query(getTable(), getColumns(), DBHelper.ID_COL + "=?", new String[] { itemID }, null, null,
					null);
			if (cursor.moveToNext()) {
				entity = getItem(cursor);
			}
		} finally {
			close(cursor, db);
		}
		return entity;
	}

	public T queryItem(String selection, String ...selectionArgs) {
		DBHelper dbHelper = DBHelper.getInstance();;
		T entity = null;

		SQLiteDatabase db = null;
		Cursor cursor = null;
		try {
			db = dbHelper.getReadableDatabase();
			cursor = db.query(getTable(), getColumns(), selection, selectionArgs, null, null,
					null);
			if (cursor.moveToNext()) {
				entity = getItem(cursor);
			}
		} finally {
			close(cursor, db);
		}
		return entity;
	}
	
	/**
	 * 删除一批实体
	 * 
	 * @param ids
	 *            要删除的那些实体的id数组
	 */
	public void deleteItems(String[] ids) {

		if (ids == null || ids.length == 0)
			return;

		DBHelper dbHelper = DBHelper.getInstance();;
		SQLiteDatabase db = null;

		try {
			db = dbHelper.getWritableDatabase();
			db.beginTransaction();

			StringBuilder sb = new StringBuilder();

			for (int i = 0, len = ids.length; i < len; i++) {
				if (i == 0) {
					sb.append("(");
				}
				if (i != len - 1) {
					sb.append("?,");
				} else {
					sb.append("?)");
				}
			}

			db.delete(getTable(), DBHelper.ID_COL + " in" + sb.toString(), ids);

			db.setTransactionSuccessful();
		} finally {
			db.endTransaction();
			close(null, db);
		}

	}

	/**
	 * 删除一批实体
	 * 
	 * @param dels
	 *            要删除的实体的id串，用“，”分隔
	 */
	public void deleteItems(String dels) {
		String[] ids = dels.split(",");
		deleteItems(ids);
	}

	/**
	 * 删除对应表中的所有数据
	 */
	public void clearItems() {
		DBHelper dbHelper = DBHelper.getInstance();;
		SQLiteDatabase db = null;
		try {
			db = dbHelper.getWritableDatabase();
			db.delete(getTable(), null, null);
		} finally {
			close(null, db);
		}
	}
	
	
	protected void clearItems( String whereClause, String[] whereArgs){
		DBHelper dbHelper = DBHelper.getInstance();;
		SQLiteDatabase db = null;
		try {
			db = dbHelper.getWritableDatabase();
			db.delete(getTable(), whereClause, whereArgs);
		} finally {
			close(null, db);
		}
	}
	

	/**
	 * 提供给子类的一个便捷办法，用于删除指定外键的数据
	 * 
	 * @param foreignColumn
	 *            外键列名
	 * @param foreignKeys
	 *            外键id集合，以1，2，3，4的形式表示
	 */
	protected void deleteByParentsIds(String foreignColumn, String foreignKeys) {
		if (foreignKeys == null)
			return;
		String[] _ids = foreignKeys.split(",");
		if (_ids.length == 0)
			return;
		DBHelper dbHelper = DBHelper.getInstance();;
		SQLiteDatabase db = null;

		try {
			db = dbHelper.getWritableDatabase();

			db.beginTransaction();

			StringBuilder sb = new StringBuilder();

			for (int i = 0, len = _ids.length; i < len; i++) {
				if (i == 0) {
					sb.append("(");
				}
				if (i != len - 1) {
					sb.append("?,");
				} else {
					sb.append("?)");
				}
			}

			db.delete(getTable(), foreignColumn + " in" + sb.toString(), _ids);

			db.setTransactionSuccessful();
		} finally {
			db.endTransaction();
			close(null, db);
		}
	}

	/** 返回表中总行数 */
	public int getCount() {
		DBHelper dbHelper = DBHelper.getInstance();;
		SQLiteDatabase db = null;
		Cursor cursor = null;
		try {
			db = dbHelper.getReadableDatabase();
			cursor = db.query(getTable(), COUNT_COLUMN, null, null, null, null, null);
			cursor.moveToFirst();
			return cursor.getInt(0);
		} finally {
			close(cursor, db);
		}
	}

	/**
	 * 子类实现该方法，指明这个dao要操作的是哪张表
	 * 
	 * @return
	 */
	protected abstract String getTable();

	/**
	 * 子类实现该方法，指明当查询时，要返回表中的哪些列
	 * 
	 * @return
	 */
	protected abstract String[] getColumns();

	/**
	 * 子类实现该方法，指明当查询时，表中的一行如何封装成对象。</p>
	 * 
	 * @param cursor
	 *            正指向某一行的游标，这一行的列名和顺序就是你通过{@link #getColumns()}指定的
	 * @return
	 */
	protected abstract T getItem(Cursor cursor);

	/**
	 * 子类实现该方法，指明如何将一个对象映射成表中的一行
	 * 
	 * @param values
	 *            以键值对的形式指明表中的某一列对应对象的哪个属性
	 * @param entity
	 *            要保存到数据库中的对象
	 */
	protected abstract void setItem(ContentValues values, T entity);

	/**
	 * 子类实现该方法，指明当查询返回一个列表时，排序的规则
	 * 
	 * @return
	 */
	protected abstract String getOrderBy();
}
